package com.gao.b_channel.b;

import org.junit.Test;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

/**
 * @author gao
 * @time 2020/06/19 09:50:25
 */
public class App {
    // 使用ByteBuffer.allocateDirect(10)来创建直接缓冲区
    @Test
    public void test() throws IOException {
        ByteBuffer buf = ByteBuffer.allocateDirect(10);

        FileChannel srcChannel = FileChannel.open(Paths.get("file\\1.txt"), StandardOpenOption.READ);
        FileChannel destChannel = FileChannel.open(Paths.get("file\\2.txt"), StandardOpenOption.WRITE, StandardOpenOption.CREATE);

        while (srcChannel.read(buf) > 0) {
            buf.flip();
            destChannel.write(buf);
            buf.clear();
        }

        srcChannel.close();
        destChannel.close();
    }

    // 使用FileChannel的map方法来创建直接映射缓冲区
    @Test
    public void test2() throws IOException {
        FileChannel srcChannel = FileChannel.open(Paths.get("file\\1.txt"), StandardOpenOption.READ);
        FileChannel destChannel = FileChannel.open(Paths.get("file\\2.txt"), StandardOpenOption.WRITE, StandardOpenOption.CREATE);

        // 在直接缓冲区中映射整个1.txt文件，如果文件特别大，则会抛出OutOfMemoryError
        MappedByteBuffer inMappedBuffer = srcChannel.map(FileChannel.MapMode.READ_ONLY, 0, srcChannel.size());

        // 将直接映射缓冲区中的内容，写入另一个通道中，完成文件复制
        destChannel.write(inMappedBuffer);

        srcChannel.close();
        destChannel.close();
    }

    @Test
    public void test3() throws IOException {
        long start = System.currentTimeMillis();
        FileChannel srcChannel = FileChannel.open(Paths.get("F:\\game\\sgzwljqb.zip"), StandardOpenOption.READ);
        FileChannel destChannel = FileChannel.open(Paths.get("F:\\test\\sgz.zip"), StandardOpenOption.WRITE, StandardOpenOption.CREATE);
        long maxSize = srcChannel.size();
        long size = 1024 * 1024 * 8;
        long position = 0;

        while (position < maxSize) {
            if (position + size > maxSize) {
                size = maxSize - position;
            }
            // 每次都映射大文件的一部分
            MappedByteBuffer buffer = srcChannel.map(FileChannel.MapMode.READ_ONLY, position, size);
            position += size;
            destChannel.write(buffer);
        }
        srcChannel.close();
        destChannel.close();
        System.out.println("MappedByteBuffer: " + (System.currentTimeMillis() - start));
    }

}
